package com.engr.config;

import com.engr.auth.CustomUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
import org.springframework.security.web.session.HttpSessionEventPublisher;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig {
    /**
     *  所有  "/assets/**", "/css/**",  "/js/**", "/video/**", "/vendors/**","/changeLocale","/fonts/**"
     */
    public static String[] ignoreUrls = {"/api/**", "/swagger-ui.html", "/swagger-resources/**", "/v2/api-docs/**",
            "/webjars/**","/images/**","/configuration/*" };
    /** 匿名用户 */
    public static String[] anonymousUrls = {};

    @Order
    @Configuration
    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();
            //所有请求放行
            http.authorizeRequests().antMatchers(ignoreUrls).permitAll()
                    //
                    .antMatchers(anonymousUrls).anonymous()
                    //其它地址的访问需要权限
                    .anyRequest().authenticated()
                    //
                    .and()
                    //
                    .formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
                    //
                    .and()
                    //
                    .logout().logoutUrl("/logout").logoutSuccessUrl("/login?logout").deleteCookies("JSESSIONID")
                    .permitAll()
                    //
                    .and()
                    //
                    .exceptionHandling()
                    //
                    .and()
                    //
                    .rememberMe()
                    //
                    .and()
                    //
                    .sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(false).expiredUrl("/login?expired")
                    .sessionRegistry(sessionRegistry());
        }

        @Bean
        public SessionRegistry sessionRegistry() {
            SessionRegistry sessionRegistry = new SessionRegistryImpl();
            return sessionRegistry;
        }

        @Bean
        public static HttpSessionEventPublisher httpSessionEventPublisher() {
            return new HttpSessionEventPublisher();
        }

    }

    @Bean
    public SecurityEvaluationContextExtension expressionEvaluationContextProvider() {
        return new SecurityEvaluationContextExtension();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Order(Ordered.HIGHEST_PRECEDENCE)
    @Configuration
    protected static class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {
        @Autowired
        private PasswordEncoder passwordEncoder;
        @Autowired
        private CustomUserDetailService customUserDetailService;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customUserDetailService).passwordEncoder(passwordEncoder);
        }
    }

}
